/**
 * Copyright 2020 Nickbing Lao<giscafer@outlook.com>
 All rights reserved.

 Redistribution and use in source and binary forms, with or without modification,
 are permitted provided that the following conditions are met:

 * Redistributions of source code must retain the above copyright notice, this
 list of conditions and the following disclaimer.

 * Redistributions in binary form must reproduce the above copyright notice,
 this list of conditions and the following disclaimer in the documentation
 and/or other materials provided with the distribution.

 * Neither the name of the author nor the names of contributors may be used to
 endorse or promote products derived from this software without specific prior
 written permission.

 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
/**
 * @abstract
 * 本源文件请求解析 sina 网络请求部分代码使用 韭菜盒子 https://github.com/LeekHub/leek-fund
 * 位于 listHQ 函数中
 */
// @ts-nocheck
import http from '@ohos.net.http';
import util from '@ohos.util';
import data_preferences from '@ohos.data.preferences';

import { calcFixedPriceNumber, randHeader, formatNumber } from './utils';
import { CompleteItem } from "./Entity";


function race({promise, timeout}) {
  let timer = null;
  return Promise.race([
    new Promise((resolve, reject) => {
      timer = setTimeout(reject, timeout);
      resolve([])
    }),
  promise.then((value) => {
    clearTimeout(timer);
    return value;
  })
  ]);
}

class StockService {
  token = '';
  codes = ["sh000001",
    "sh000300",
    "hk00700",
    "usr_ixic",
    "usr_dji",
    "usr_inx",
    "nf_IH0",
    "nf_IF0",
    "nf_IC0",
    "nf_IM0",
    "hf_OIL",
    "hf_CHA50CFD",
    "nf_SR0",
  ];
  pref: data_preferences.Preferences = null;

  async search(text) {
    const timestamp = new Date().valueOf();
    // 11 A股，85、86、88 期货
    const stockUrl = `https://suggest3.sinajs.cn/suggest/type=85,86,88,11&key=${text}&name=suggestdata_${timestamp}`;
    console.info("stockUrl " + stockUrl)
    const req = http.createHttp();
    const data = await req.request(stockUrl, {
      expectDataType: http.HttpDataType.ARRAY_BUFFER, // 可选，指定返回数据的类型
      header: {
        //                ...randHeader(),
        Referer: 'https://finance.sina.com.cn/stock/',
      },
    });

    var ret = [];
    {
      // data.result为HTTP响应内容，可根据业务需要进行解析
      var decoder = new util.TextDecoder('GB18030')
      // @ts-ignore
      const z = new Uint8Array(data.result);
      let dec = decoder.decode(z);
      console.log("content:" + dec);
      let liststr = dec.split('"')[1];
      if (liststr.length == 0) return ret;
      let line = liststr.split(';');
      console.log(line.join("\n"))
      line.forEach(it => {
        const cells = it.split(',');
        const item = new CompleteItem();
        item.code = cells[3];
        item.fcode = cells[0];
        item.exchange = cells[1] || '';
        item.name = cells[4] || '';
        ret.push(item)
      })
      console.info('code:' + JSON.stringify(data.responseCode));
      console.info('header:' + JSON.stringify(data.header));
      console.info('cookies:' + JSON.stringify(data.cookies)); // 8+
    }

    return ret
  }

  async listHQ() {
    const getLocalCodes = await this.getToLocal();
    if(getLocalCodes.length>0){
      this.codes = getLocalCodes;
    }
    const url = `https://hq.sinajs.cn/list=${this.codes.join(',')}`;
    const req = http.createHttp();
    const data = await req.request(url, {
      expectDataType: http.HttpDataType.ARRAY_BUFFER, // 可选，指定返回数据的类型
      header: {
        ...randHeader(),
        Referer: 'https://finance.sina.com.cn/stock/',
      },
    });

    ////
    const stocks = [];
    {
      // data.result为HTTP响应内容，可根据业务需要进行解析
      var decoder = new util.TextDecoder('GB18030')
      // @ts-ignore
      const z = new Uint8Array(data.result);
      let res = decoder.decode(z);

      const splitData = res.split(';\n');

      for (let i = 0; i < splitData.length - 1; i++) {
        const code = splitData[i].split('="')[0].split('var hq_str_')[1];
        const params = splitData[i].split('="')[1].split(',');
        let type = code.substr(0, 2) || 'sh';
        let symbol = code.substr(2);
        let stockItem: any;
        let fixedNumber = 2;
        if (params.length > 1) {
          if (/^(sh|sz)/.test(code)) {
            let open = params[1];
            let yestclose = params[2];
            let price = params[3];
            let high = params[4];
            let low = params[5];
            fixedNumber = calcFixedPriceNumber(open, yestclose, price, high, low);
            stockItem = {
              code,
              name: params[0],
              open: formatNumber(open, fixedNumber, false),
              yestclose: formatNumber(yestclose, fixedNumber, false),
              price: formatNumber(price, fixedNumber, false),
              low: formatNumber(low, fixedNumber, false),
              high: formatNumber(high, fixedNumber, false),
              volume: formatNumber(params[8], 2),
              amount: formatNumber(params[9], 2),
              time: `${params[30]} ${params[31]}`,
              percent: '',
            };
            // aStockCount += 1;
          } else if (/^gb_/.test(code)) {
            symbol = code.substr(3);
            let open = params[5];
            let yestclose = params[26];
            let price = params[1];
            let high = params[6];
            let low = params[7];
            fixedNumber = calcFixedPriceNumber(open, yestclose, price, high, low);
            stockItem = {
              code,
              name: params[0],
              open: formatNumber(open, fixedNumber, false),
              yestclose: formatNumber(yestclose, fixedNumber, false),
              price: formatNumber(price, fixedNumber, false),
              low: formatNumber(low, fixedNumber, false),
              high: formatNumber(high, fixedNumber, false),
              volume: formatNumber(params[10], 2),
              amount: '接口无数据',
              percent: '',
            };
            type = code.substr(0, 3);
            // noDataStockCount += 1;
          } else if (/^usr_/.test(code)) {
            symbol = code.substr(4);
            let open = params[5];
            let yestclose = params[26];
            let price = params[1];
            let high = params[6];
            let low = params[7];
            fixedNumber = calcFixedPriceNumber(open, yestclose, price, high, low);
            stockItem = {
              code,
              name: params[0],
              open: formatNumber(open, fixedNumber, false),
              yestclose: formatNumber(yestclose, fixedNumber, false),
              price: formatNumber(price, fixedNumber, false),
              low: formatNumber(low, fixedNumber, false),
              high: formatNumber(high, fixedNumber, false),
              volume: formatNumber(params[10], 2),
              amount: '接口无数据',
              percent: '',
            };
            type = code.substr(0, 4);
            // usStockCount += 1;
          } else if (/nf_/.test(code)) {
            /* 解析格式，与股票略有不同
            var hq_str_V2201="PVC2201,230000,
            8585.00, 8692.00, 8467.00, 8641.00, // params[2,3,4,5] 开，高，低，昨收
            8673.00, 8674.00, // params[6, 7] 买一、卖一价
            8675.00, // 现价 params[8]
            8630.00, // 均价
            8821.00, // 昨日结算价【一般软件的行情涨跌幅按这个价格显示涨跌幅】（后续考虑配置项，设置按收盘价还是结算价显示涨跌幅）
            109, // 买一量
            2, // 卖一量
            289274, // 持仓量
            230643, //总量
            连, // params[8 + 7] 交易所名称 ["连","沪", "郑"]
            PVC,2021-11-26,1,9243.000,8611.000,9243.000,8251.000,9435.000,8108.000,13380.000,8108.000,445.541";
            */
            let name = params[0];
            let open = params[2];
            let high = params[3];
            let low = params[4];
            // let yestclose = params[5]; // 昨收盘。但是这个字段不返回数据。
            let price = params[8];
            let yestCallPrice = params[8 + 2]; // 结算价
            /*
              由于期货默认采用结算价计算涨跌幅。本项目的涨跌幅使用【昨收盘】进行计算，
              新浪接口对于商品期货的 昨收盘返回 0.0，导致无法计算【昨收盘涨跌幅】，只能计算【结算涨跌幅】。
              使用期货的结算价对应 股票通用的 【昨收盘 yestclose】字段以方便计算涨跌幅的显示。
            */
            let yestclose = params[8 + 2];
            let volume = params[8 + 6]; // 成交量
            //股指期货
            const stockIndexFuture = /nf_IC/.test(code) // 中证500
            || /nf_IF/.test(code) // 沪深300
            || /nf_IH/.test(code) // 上证50
            || /nf_IM/.test(code) // 中证 1000
            || /nf_TF/.test(code) // 五债
            || /nf_TS/.test(code) // 二债
            || /nf_T\d+/.test(code) // 十债
            || /nf_TL/.test(code) // 三十年国债
            ;
            if (stockIndexFuture) {
              // 0 开盘       1 最高      2  最低     3 收盘
              // ['5372.000', '5585.000', '5343.000', '5581.600',
              // 4 成交量                 6 持仓量
              // '47855', '261716510.000', '124729.000', '5581.600',
              // '0.000', '5849.800', '4786.200', '0.000', '0.000',
              //  13 昨收盘   14 昨天结算
              // '5342.800', '5318.000', '126776.000', '5581.600',
              // '4', '0.000', '0', '0.000', '0', '0.000', '0', '0.000', '0', '5582.000', '2', '0.000', '0', '0.000', '0', '0.000', '0', '0.000', '0', '2022-04-29', '15:00:00', '300', '0', '', '', '', '', '', '', '', '',
              // 48        49  名称
              // '5468.948', '中证500指数期货2206"']

              name = params[49].slice(0, -1); // 最后一位去掉 "
              open = params[0];
              high = params[1];
              low = params[2];
              price = params[3];
              volume = params[4];
              yestclose = params[13];
              yestCallPrice = params[14];
            }
            fixedNumber = calcFixedPriceNumber(open, yestclose, price, high, low);
            stockItem = {
              code: code,
              name: name,
              open: formatNumber(open, fixedNumber, false),
              yestclose: formatNumber(yestclose, fixedNumber, false),
              yestcallprice: formatNumber(yestCallPrice, fixedNumber, false),
              price: formatNumber(price, fixedNumber, false),
              low: formatNumber(low, fixedNumber, false),
              high: formatNumber(high, fixedNumber, false),
              volume: formatNumber(volume, 2),
              amount: '接口无数据',
              percent: '',
            };
            type = 'nf_';
            // cnfStockCount += 1;
          } else if (/hf_/.test(code)) {
            // 海外期货格式
            // 0 当前价格
            // ['105.306', '',
            //  2  买一价  3 卖一价  4  最高价   5 最低价
            // '105.270', '105.290', '105.540', '102.950',
            //  6 时间   7 昨日结算价  8 开盘价  9 持仓量
            // '15:51:34', '102.410', '103.500', '250168.000',
            // 10 买 11 卖 12 日期      13 名称  14 成交量
            // '5', '2', '2022-05-04', 'WTI纽约原油2206', '28346"']
            // 当前价格
            let price = params[0];
            // 名称
            let name = params[13];
            let open = params[8];
            let high = params[4];
            let low = params[5];
            let yestclose = params[7]; // 昨收盘
            let yestCallPrice = params[7]; // 昨结算
            let volume = params[14].slice(0, -1); // 成交量。slice 去掉最后一位 "
            fixedNumber = calcFixedPriceNumber(open, yestclose, price, high, low);

            stockItem = {
              code: code,
              name: name,
              open: formatNumber(open, fixedNumber, false),
              yestclose: formatNumber(yestclose, fixedNumber, false),
              yestcallprice: formatNumber(yestCallPrice, fixedNumber, false),
              price: formatNumber(price, fixedNumber, false),
              low: formatNumber(low, fixedNumber, false),
              high: formatNumber(high, fixedNumber, false),
              volume: formatNumber(volume, 2),
              amount: '接口无数据',
              percent: '',
            };
            type = 'hf_';
            // hfStockCount += 1;
          }
          if (stockItem) {
            const { yestclose, open } = stockItem;
            let { price } = stockItem;
            /*  if (open === price && price === '0.00') {
            stockItem.isStop = true;
          } */

            // 竞价阶段部分开盘和价格为0.00导致显示 -100%
            try {
              if (Number(open) <= 0) {
                price = yestclose;
              }
            } catch (err) {
              console.error(err);
            }
            // stockItem.showLabel = this.showLabel;
            stockItem.isStock = true;
            stockItem.type = type;
            stockItem.symbol = symbol;
            stockItem.updown = formatNumber(+price - +yestclose, fixedNumber, false);
            stockItem.percentValue = stockItem.updown / yestclose;
            stockItem.percent =
            (stockItem.updown >= 0 ? '+' : '-') +
            formatNumber((Math.abs(stockItem.updown) / +yestclose) * 100, 2, false);

            // const treeItem = new LeekTreeItem(stockItem, this.context);
            // stockList.push(treeItem);
          }
        } else {
          // 接口不支持的
          // noDataStockCount += 1;
          stockItem = {
            id: code,
            name: `接口不支持该股票 ${code}`,
            // showLabel: this.showLabel,
            isStock: true,
            percent: '',
            type: 'nodata',
            contextValue: 'nodata',
          };
          // const treeItem = new LeekTreeItem(stockItem, this.context);
          // stockList.push(treeItem);
        }

        if (stockItem) {
          if(stockItem.type!='nodata'){
            stocks.push(stockItem);
          }
        }
      }
    }

    return stocks
  }

  removeCode(code) {
    const codes = this.codes.filter(it => it != code);
    this.codes = codes;
    this.saveToLocal();
  }

  addCode(code) {
    this.codes.push(code);
    this.saveToLocal();
  }

  saveToLocal() {
    console.log("存储codes")
    if (this.pref) {
      console.log("存储成功")
      this.pref.put('MyCodes', this.codes);
      this.pref.flush();
    }
  }

  async getToLocal(){
    return this.pref.get('MyCodes', []);
    // let rec = race({promise: this.pref.get('MyCodes', []), timeout: 500})
    // return rec;
  }
}

export default StockService;